

#region Using Statements
using System;
using System.Collections.Generic;
//using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion


namespace Pauliver
{

    public enum TeamType{Local,AI,Network};

    public class UserTeamPlayer
    {
        protected AvailableWeaponList _AWL;
        protected Team _Team;
        protected TeamType _TeamType;
        protected LinkedList<PlayerIndex> _HumanPlayers;
        protected LinkedList<PlayerObject> _Avatars;
        protected LinkedListNode<PlayerIndex> _CurrentPlayer;
        protected LinkedListNode<PlayerObject> _CurrentAvatar;

        public UserTeamPlayer(Team p_Team,TeamType p_TeamType)
        {
            _AWL = new AvailableWeaponList();
            _Team = p_Team;
            _HumanPlayers = new LinkedList<PlayerIndex>();
            _Avatars = new LinkedList<PlayerObject>();
            _TeamType = p_TeamType;
        }

        public AvailableWeaponList AvailableWeapons
        {
            get
            {
                return _AWL;   
            }
        }

        public TeamType TeamType
        {
            get
            {
                return _TeamType;
            }
            set
            {
                _TeamType = value;
            }
        }
        
        public LinkedList<PlayerObject> Avatars
        {
            get
            {
                return _Avatars;
            }
        }

        public void AddPlayer(PlayerIndex player)
        {
            _HumanPlayers.AddLast(player);
        }

        public void AddAvatar(PlayerObject avatar)
        {
            _Avatars.AddLast(avatar);
        }

        public void Setup()
        {
            _CurrentAvatar = _Avatars.First;
            _CurrentPlayer = _HumanPlayers.First;
        }

        public Team Team
        {
            get
            {
                return _Team;
            }
        }

        public PlayerObject CurrentAvatar
        {
            get
            {
                return _CurrentAvatar.Value;
            }
        }

        public PlayerIndex CurrentPlayer
        {
            get
            {
                return _CurrentPlayer.Value;
            }
        }

        public void AdvanceTurn()
        {
            AdvanceAvatar();
            AdvancePlayer();
        }

        public void AdvanceAvatar()
        {
            if (_CurrentAvatar == _Avatars.Last)
            {
                _CurrentAvatar = _Avatars.First;
            }
            else
            {
                _CurrentAvatar = _CurrentAvatar.Next;
            }
        }

        public void AdvancePlayer()
        {
            if (_CurrentPlayer == _HumanPlayers.Last)
            {
                _CurrentPlayer = _HumanPlayers.First;
            }
            else
            {
                _CurrentPlayer = _CurrentPlayer.Next;
            }
        }
    
        public bool RemovePlayer(PlayerIndex player)
        {
            bool retval = false;
            if(_CurrentPlayer.Value == player)
            {
                if(_HumanPlayers.Count == 1)
                {
                    retval = true;
                }
            }
            _HumanPlayers.Remove(player);
            if(retval)
            {
                _HumanPlayers = null;
                _CurrentPlayer = null;
            }
            return retval;
        }
        
        public bool RemoveAvatar(PlayerObject avatar)
        {
            bool retval = false;
            if (avatar == _CurrentAvatar.Value)
            {
                if (_Avatars.Count == 1)
                {
                    retval = true;
                }else{
                    AdvanceAvatar();
                }

            }
            _Avatars.Remove(avatar);
            if (retval)
            {
                _Avatars = null;
                _CurrentAvatar = null;
            }
            return retval;
        }
    
        public int AvatarCount
        {
            get
            {
                return _Avatars.Count;
            }
        }

        public int TotalHP()
        {
            int hp = 0;
            foreach (PlayerObject po in _Avatars)
            {
                hp += (po[ComponentType.Game_Hitpoint] as Game_Hitpoints).Hitpoints;
            }
            return hp;
        }
    }

    public class UserTeamPlayerManager
    {
        protected LinkedList< UserTeamPlayer > _TurnList;
        protected LinkedListNode<UserTeamPlayer> _Current;
        public UserTeamPlayerManager()
        {
            _TurnList = new LinkedList<UserTeamPlayer>();
        }
        public void Setup()
        {
            foreach(UserTeamPlayer utp in _TurnList )
            {
                utp.Setup();
            }
            _Current = _TurnList.First;
        }
        public UserTeamPlayer Current
        {
            get
            {
                return _Current.Value;
            }
        }
        public PlayerIndex CurrentPlayer
        {
            get
            {
                return _Current.Value.CurrentPlayer;
            }
        }
        public PlayerObject CurrentAvatar
        {
            get
            {
                return _Current.Value.CurrentAvatar;
            }
        }
        public Team CurrentTeam
        {
            get
            {
                return _Current.Value.Team;
            }
        }

        public void AddTeam(Team team,TeamType teamtype)
        {
            //Can add 2 copies of the same team...
            _TurnList.AddLast(new UserTeamPlayer(team,teamtype));
        }

        public void AddPlayerToTeam(Team team, PlayerIndex player)
        {
            foreach(UserTeamPlayer node in _TurnList)
            {
                if(node.Team == team)
                {
                    node.AddPlayer(player);
                }
            }
        }

        public PlayerIndex? SwapTeamType(Team team, TeamType type)
        {
            foreach(UserTeamPlayer node in _TurnList)
            {
                if(node.Team == team)
                {
                    node.TeamType = type;
                    return node.CurrentPlayer;
                }
            }
            return null;
        }

        public void AddAvatarToTeam(Team team,PlayerObject avatar)
        {
            foreach (UserTeamPlayer node in _TurnList)
            {
                if (node.Team == team)
                {
                    node.AddAvatar(avatar);
                }
            }
        }

        private bool RemovePlayer(PlayerIndex player)
        {
            bool gone = false;
            UserTeamPlayer removeme = null;
            //if we allow one player on more than one team
            // or we ever use this method
            // it needs to be thought through futher
            foreach (UserTeamPlayer node in _TurnList)
            {
                if (node.RemovePlayer(player))
                {
                    gone = true;
                    removeme = node;
                    if (removeme == _Current.Value)
                    {
                        _Current = null;
                    }
                }
            }
            if (gone)
            {
                _TurnList.Remove(removeme);
                removeme = null;
            }
            return gone;
        }

        private bool RemoveAvatar(Team team, PlayerObject avatar)
        {
            bool gone = false;
            List<UserTeamPlayer> removeme = new List<UserTeamPlayer>();
            foreach (UserTeamPlayer node in _TurnList)
            {
                if (team == node.Team)
                {
                    if (node.RemoveAvatar(avatar))
                    {
                        gone = true;
                        removeme.Add(node);
                        if (node == _Current.Value)
                        {
                            Advance();
                        }
                    }
                }
            }
            if (gone)
            {
                foreach (UserTeamPlayer rm in removeme)
                {
                    _TurnList.Remove(rm);
                }
            }
            return gone;
        }

        private bool RemovePlayer(Team team, PlayerIndex Player)
        {
            System.Diagnostics.Debug.Assert(false);//copy code from above
            //this hasn't been updated
            bool gone = false;
            UserTeamPlayer removeme = null;
            //if we allow one player on more than one team
            // or we ever use this method
            // it needs to be thought through futher
            foreach (UserTeamPlayer node in _TurnList)
            {
                if (team == node.Team)
                {
                    if (node.RemovePlayer(Player))
                    {
                        gone = true;
                        removeme = node;
                        if (removeme == _Current.Value)
                        {
                            _Current = null;
                        }
                    }
                }
            }
            if (gone)
            {
                _TurnList.Remove(removeme);
                removeme = null;
            }
            return gone;
        }

        public bool RemoveAvatar(PlayerObject avatar)
        {
            bool gone = false;
            List<UserTeamPlayer> removeme = new List<UserTeamPlayer>();
            foreach ( UserTeamPlayer node in _TurnList)
            {
                if(node.RemoveAvatar(avatar))
                {
                    //@@ we are advancing twice 
                    // this needs a fix
                    gone = true;
                    removeme.Add(node);
                    if (node == _Current.Value)
                    {
                        AdvancePlayerOnly();
                    }
                }
            }
            if(gone)
            {
                foreach(UserTeamPlayer rm in removeme)
                {
                    _TurnList.Remove(rm);
                }
            }
            return gone;
        }
        public void AdvancePlayerOnly()
        {
            if (_Current != null)
            {
                if (_Current.Next == null)
                {
                    _Current = _TurnList.First;
                }
                else
                {
                    _Current = _Current.Next;
                }
            }
            else
            {
                if (_TurnList.Count > 0)
                {
                    _Current = _TurnList.First;
                }
                else
                {

                }
            }
        }

        public void Advance()
        {
            if(_Current != null)
            {
                _Current.Value.AdvanceTurn();
                if (_Current.Next == null)
                {
                    _Current = _TurnList.First;
                }else{
                    _Current = _Current.Next;
                }
            }else{
                if(_TurnList.Count > 0)
                {
                    _Current = _TurnList.First;
                }else{
                    //WTF do i do now?
                }
            }
        }

        public void FakeAdvance()
        {
            //Do nothing
        }

        public LinkedList< UserTeamPlayer > PlayerManagers
        {
            get
            {
                return _TurnList;
            }
        }

        public Team GetWinningTeam()
        {
            if (_TurnList.Count > 1)
            {
                return Team.NoTeam;
            }
            else if (_TurnList.Count == 0)
            {
                return Team.NoOneLeft;
            }
            else
            {
                return _TurnList.First.Value.Team;
            }
        }
    
        public List<Team> GetTeams()
        {
            List<Team> teamlist = new List<Team>();
            foreach( UserTeamPlayer t in _TurnList)
            {
                if (!teamlist.Contains(t.Team))
                {
                    teamlist.Add(t.Team);
                }
            }
            return teamlist;
        }

        public List<PlayerObject> GetEnemyAvatars()
        {
            List<PlayerObject> playerlist = new List<PlayerObject>();
            foreach (UserTeamPlayer t in _TurnList)
            {
                foreach (PlayerObject p in t.Avatars)

                    if (!playerlist.Contains(p) && p.Team != CurrentTeam)
                    {
                        playerlist.Add(p);
                    }
            }
            return playerlist;
        }

        public int TotalPlayerCount()
        {
            int count = 0;
            foreach (UserTeamPlayer t in _TurnList)
            {
                count += t.AvatarCount;
            }
            return count;
        }
    }
}